#ifndef _SMART_DEVICE_PROTOCOL_HEAD_H
#define _SMART_DEVICE_PROTOCOL_HEAD_H
#include <istream>
#include <vector>
using namespace std;

#define SMART_DEVICE_PROTOCOL_PACKET_FIX_LEN (9)

extern uint16_t calc_crc16(unsigned char *buf, int len);

class SmartDeviceProtocol
{
public:
    typedef struct
    {
        uint8_t head[2];
        uint8_t addr[4];
        uint8_t pid;
        uint8_t len[2];
        uint8_t data[1];
    } packet_t;

    enum
    {
        DOOR_LOCK_DEVICE_ADDR = 0x00000001,  // 门锁
        ELECTRICAL_DEVICE_ADDR = 0x00000002, // 电器
        SENSOR_DEVICE_ADDR = 0x00000003,     // 传感器
        SNIFFING_DEVICE_ADDR = 0xffffffff,   // 嗅探设备

    };

    enum
    {
        REQ_PACKET = 0x01,
        ACK_PACKET = 0x02,
    };

    enum
    {
        HANDLE_SUCCESS = 0x00,
        HANDLE_FIALURE = 0x01,
        PACKET_ERROR = 0x02,
    };

    SmartDeviceProtocol();
    SmartDeviceProtocol(const vector<uint8_t> &packet);
    // 添加地址
    void addPacketHead(uint16_t head = 0xffff);
    void addDeiceAddress(uint32_t addr);
    void addPacketID(uint8_t id);
    void addPacketData(uint8_t *data, uint16_t size);
    void addPacketCRC16(void);
    uint8_t *packetData(void);
    uint16_t packetLen(void);

    uint16_t getPacketHead(void) const;
    uint32_t getPacketAddr(void) const;
    uint8_t getPacketID(void) const;
    uint16_t getPacketDataLen(void) const;
    uint8_t *getPacketData(void) const;
    uint16_t getPacketCRC16(void) const;
    uint8_t getPacketErrorCode(void) const;
    void showPacket(void) const;
    bool isErrorPakcet(void);

    static SmartDeviceProtocol makeDoorLockProtocol(uint8_t deviceType,
                                                    uint8_t opcode,
                                                    uint8_t deviceNumber);

    static SmartDeviceProtocol makeElectricalProtocol(uint8_t deviceType,
                                                      uint8_t opcode,
                                                      uint8_t deviceNumber);

    static SmartDeviceProtocol makeSensorProtocol(uint8_t deviceType,
                                                  uint8_t opcode,
                                                  uint8_t deviceNumber);

    static SmartDeviceProtocol makeSniffingProtocol(uint8_t deviceType,
                                                    uint8_t opcode,
                                                    uint8_t deviceNumber);

    static SmartDeviceProtocol makeProtocolFormPacket(const vector<uint8_t> &packet);

private:
    vector<uint8_t> packet;
};

#endif